﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;

namespace SuperSerialization
{
    /// <summary>
    /// The main class of SuperSerial.
    /// </summary>
    public class Serializer
    {
        /// <summary>
        /// Private constructor to prevent outside initialization, since the methods in this class are static (for now)
        /// </summary>
        // TODO: Consider allowing/requiring serializer instances. The static methods can be kept as long as they just create a new instance and use that.
        private Serializer()
        {

        }

        /// <summary>
        /// Attempts to deserialize a text stream into an in-memory object.
        /// </summary>
        /// <param name="type">The expected type of the deserialized object.</param>
        /// <param name="reader">The reader to use.</param>
        /// <returns>An object.</returns>
        public static Object Deserialize(Type type, TextReader reader)
        {
            return Deserialize(type.Assembly, reader);
        }

        /// <summary>
        /// Attempts to deserialize a text stream into an in-memory object.
        /// </summary>
        /// <param name="assembly">The assembly that the object's type might reside in.</param>
        /// <param name="reader">The reader to use.</param>
        /// <returns>An object.</returns>
        public static Object Deserialize(Assembly assembly, TextReader reader)
        {
            Parser parser = new Parser(reader);
            Tree.Node node = parser.Parse();
            if (node == null) throw new ParseException("Could not parse data file");
            TreeVisitor.DeserializationVisitor visitor = new TreeVisitor.DeserializationVisitor(assembly);
            node.Accept(visitor);
            return visitor.Object;
        }

        /// <summary>
        /// Attempts to serialize an object into text.
        /// </summary>
        /// <param name="writer">The output writer.</param>
        /// <param name="obj">The object to serialize.</param>
        public static void Serialize(TextWriter writer, Object obj)
        {
            Serialize(writer, obj, true);
        }

        /// <summary>
        /// Attempts to serialize an object into text.
        /// </summary>
        /// <param name="writer">The output writer.</param>
        /// <param name="obj">The object to serialize.</param>
        /// <param name="humanReadable">Determines whether the output has multiple lines.</param>
        public static void Serialize(TextWriter writer, Object obj, bool humanReadable)
        {
            Tree.Node node = ObjectConverter.Convert(obj);
            TreeVisitor.SerializationVisitor printer = new TreeVisitor.SerializationVisitor(writer, humanReadable);
            node.Accept(printer);
        }
    }
}
